using System;
using System.IO;
using SimpleCore.Tool;
using UnityEditor;
using UnityEngine;

namespace SimpleEditor.NoiseCreator
{
    /// <summary>
    /// 创建噪声图工具
    /// 基于https://github.com/Auburns/FastNoise_CSharp生成
    /// </summary>
    public class NoiseCreator : EditorWindow
    {
        [MenuItem("Simple Tools/Others/噪声图创建")]
        static void OpenWindow()
        {
            var window = GetWindow<NoiseCreator>();
            window.name = "噪声图创建工具";
        }

        private void OnGUI()
        {
            EditorGUILayout.HelpBox("默认大小为128*128", MessageType.Info);
            _textureSize = (TextureSize)EditorGUILayout.EnumPopup("图片大小", _textureSize);
            EditorGUILayout.HelpBox("默认类型为灰度", MessageType.Info);
            _textureType = (TextureType)EditorGUILayout.EnumPopup("图片类型", _textureType);
            
            _frequency = EditorGUILayout.FloatField("频率", _frequency);
            _interp = (FastNoise.Interp)EditorGUILayout.EnumPopup("插值函数", _interp);
            _seed = EditorGUILayout.IntField("随机种子", _seed);
            _gradient = EditorGUILayout.FloatField("梯度扰动放大器", _gradient);
            _noiseType = (FastNoise.NoiseType) EditorGUILayout.EnumPopup("噪声类型", _noiseType);

            if(EditorGUILayout.BeginToggleGroup("细胞噪声设置", _noiseType == FastNoise.NoiseType.Cellular))
            {
                EditorGUILayout.HelpBox("细胞噪声图需要两个噪声对象才能正常生成，目前暂时没有做", MessageType.Warning);
//                _cellJitter = EditorGUILayout.FloatField("细胞抖动", _cellJitter);
//                _cellDistance1 = EditorGUILayout.IntField("细胞到标记的距离1", _cellDistance1);
//                _cellDistance2 = EditorGUILayout.IntField("细胞到标记的距离2", _cellDistance2);
//                _cellReturnType = (FastNoise.CellularReturnType) EditorGUILayout.EnumPopup("返回类型", _cellReturnType);
            }
            EditorGUILayout.EndToggleGroup();

            if(EditorGUILayout.BeginToggleGroup("分形", _noiseType == FastNoise.NoiseType.CubicFractal ||
                                                      _noiseType == FastNoise.NoiseType.PerlinFractal ||
                                                      _noiseType == FastNoise.NoiseType.SimplexFractal||
                                                      _noiseType == FastNoise.NoiseType.ValueFractal))
            {
                _fractalType = (FastNoise.FractalType) EditorGUILayout.EnumPopup("分形类型", _fractalType);
                _fractalGain = EditorGUILayout.FloatField("分形增益", _fractalGain);
                _fractalLacunarity = EditorGUILayout.FloatField("分形间隙", _fractalLacunarity);
                _fractalOctaves = EditorGUILayout.IntField("分形八度", _fractalOctaves);
            }
            EditorGUILayout.EndToggleGroup();


            GUILayout.Box(_texture2D);

            if (GUILayout.Button("刷新"))
            {
                RefreshNoise();
                ResizeTexture();
                FillTexture();                
            }

            if (GUILayout.Button("保存"))
            {
                SaveTexture();
            }
        }

        void ResizeTexture()
        {
            switch (_textureSize)
            {
                case TextureSize.S16:
                    EditorCommonTool.CheckAndResizeTextureSize(ref _texture2D, 16, 16);
                    break;
                case TextureSize.S32:
                    EditorCommonTool.CheckAndResizeTextureSize(ref _texture2D, 32, 32);
                    break;
                case TextureSize.S64:
                    EditorCommonTool.CheckAndResizeTextureSize(ref _texture2D, 64, 64);
                    break;
                case TextureSize.S256:
                    EditorCommonTool.CheckAndResizeTextureSize(ref _texture2D, 256, 256);
                    break;
                case TextureSize.S512:
                    EditorCommonTool.CheckAndResizeTextureSize(ref _texture2D, 512, 512);
                    break;
                case TextureSize.S1024:
                    EditorCommonTool.CheckAndResizeTextureSize(ref _texture2D, 1024, 1024);
                    break;
                case TextureSize.S2048:
                    EditorCommonTool.CheckAndResizeTextureSize(ref _texture2D, 2048, 2048);
                    break;
//                case TextureSize.Default:
//                case TextureSize.S128:
                default:
                    EditorCommonTool.CheckAndResizeTextureSize(ref _texture2D, 128, 128);
                    break;
            }
        }

        void RefreshNoise()
        {
            _fastNoise.SetCellularNoiseLookup(_fastNoise);
            _fastNoise.SetFrequency(_frequency);
            _fastNoise.SetInterp(_interp);
            _fastNoise.SetSeed(_seed);
            _fastNoise.SetNoiseType(_noiseType);
            _fastNoise.SetCellularJitter(_cellJitter);
            _fastNoise.SetCellularDistance2Indicies(_cellDistance1, _cellDistance2);
            _fastNoise.SetCellularReturnType(_cellReturnType);
            _fastNoise.SetGradientPerturbAmp(_gradient);
            _fastNoise.SetFractalType(_fractalType);
            _fastNoise.SetFractalGain(_fractalGain);
            _fastNoise.SetFractalLacunarity(_fractalLacunarity);//分形间隙
            _fastNoise.SetFractalOctaves(_fractalOctaves);
        }
        
        void FillTexture()
        {
            for (int i = 0; i < _texture2D.width; i++)
            {
                for (int j = 0; j < _texture2D.height; j++)
                {
                    var x = 1f / _texture2D.width * i;
                    var y = 1f / _texture2D.height * j;
                    var value = _fastNoise.GetNoise(x, y) + 0.5f;
                    var color = Color.white * value;
                    if (_textureType == TextureType.Gray)
                    {
                        _texture2D.SetPixel(i, j, color);
                    }
                    else if (_textureType == TextureType.FullColor)
                    {
                        value = _fastNoise.GetNoise(x * 2, y * 2) + 0.5f;
                        color.g = value;
                        value = _fastNoise.GetNoise(x * 3, y * 3) + 0.5f;
                        color.b = value;
                        value = _fastNoise.GetNoise(x * 4, y * 4) + 0.5f;
                        color.a = value;
                        _texture2D.SetPixel(i, j, color);
                    }
                }
            }
            
            _texture2D.Apply();
        }

        void SaveTexture()
        {
            string path = EditorUtility.SaveFilePanel("Save Noise Tex", Application.dataPath,
                $"noise_{DateTime.Now.ToString("yyyyMMddHHmmss")}", "png");

            var bytes = _texture2D.EncodeToPNG();
            
            File.WriteAllBytes(path, bytes);
        }
        
        
        //贴图素材相关字段
        private static TextureSize _textureSize;
        private static TextureType _textureType;
        private static Texture2D _texture2D;
        
        
        //噪声数据相关字段
        static FastNoise _fastNoise = new FastNoise();
        private float _frequency;
        private FastNoise.Interp _interp;
        private int _seed;
        private FastNoise.NoiseType _noiseType;
        private float _cellJitter = 0;
        private int _cellDistance1 = 0;
        private int _cellDistance2 = 0;
        private FastNoise.CellularReturnType _cellReturnType = FastNoise.CellularReturnType.Distance;
        private float _gradient;
        private FastNoise.FractalType _fractalType;
        private float _fractalGain;
        private float _fractalLacunarity;
        private int _fractalOctaves;
        
    }
}